package com.github.wui.WaterLampView;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;


import com.github.wui.R;
import com.github.wui.utils.ViewUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 流水灯
 *
 * @author <a href="https://github.com/karai-oss">Mr.xie</a>
 * @Date 2025/5/10
 */
public class WaterLampView extends View {


    public static enum WaterLampMode {

        SINGLE, DOUBLE, THREE,


    }


    /**
     * 字体画笔
     */
    private Paint textPaint = new Paint();


    /**
     * 字体画笔
     */
    private int textColor = Color.WHITE;

    /**
     * 字体大小
     */
    private float textSize = 300f;


    private String text = "点击输入弹幕点击输入弹幕";


    /**
     * 非单行模式下的每行之间的间距
     */
    private float space = 20f;


    /**
     * 文本开始的位置
     */
    private List<Point> textPoints = new ArrayList<>();


    private int moveDistance = 10;


    /**
     * 文字莫斯
     */

    private int mode = WaterLampMode.SINGLE.ordinal();


    /**
     * 是否开启文字闪烁
     */
    private boolean isFlash = true;


    /**
     * 文字闪烁速度
     */
    private int flashSpeed = 500;


    /**
     * 文字移动的速度
     */
    private int textSpeed = 10;


    private boolean isStart = false;

    /**
     * 控制文字移动的线程
     */
    private Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            textMove();
        }
    });


    private void textMove() {
        while (isStart) {
            updateTimerPoint();
            invalidate();
            ViewUtils.sleep(textSpeed);
        }
    }


    private void textFlash() {
        while (isFlash) {
            textPaint.setAlpha(255);
            ViewUtils.sleep(flashSpeed);
            textPaint.setAlpha(0);
            ViewUtils.sleep(flashSpeed);
        }
    }

    /**
     * 控制文字闪烁的线程
     */
    Thread flashThread = new Thread(new Runnable() {
        @Override
        public void run() {
            textFlash();
        }
    });


    public WaterLampView(Context context) {
        this(context, null);
    }

    public WaterLampView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WaterLampView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WaterLampView);

        this.text = typedArray.getString(R.styleable.WaterLampView_text) == null ? "默认文本" : typedArray.getString(R.styleable.WaterLampView_text);
        this.isFlash = typedArray.getBoolean(R.styleable.WaterLampView_isFlash, false);
        this.space = typedArray.getDimension(R.styleable.WaterLampView_lineSpace, 10f);
        this.moveDistance = (int) typedArray.getDimension(R.styleable.WaterLampView_moveDistance, 10f);
        this.textSize = typedArray.getDimensionPixelSize(R.styleable.WaterLampView_textSize, 200);
        this.textColor = typedArray.getColor(R.styleable.WaterLampView_textColor, Color.WHITE);
        this.flashSpeed = typedArray.getInteger(R.styleable.WaterLampView_flashSpeed, 500);
        this.mode = typedArray.getInteger(R.styleable.WaterLampView_mode, 0);
        this.textSpeed = typedArray.getInteger(R.styleable.WaterLampView_textSpeed, 10);
        typedArray.recycle();
        init();
    }

    private void init() {
        this.textPaint.setAntiAlias(true);
        this.textPaint.setColor(textColor);
        this.textPaint.setTextSize(textSize);
        if (isFlash) {
            flashThread.start();
        }
    }


    public void updateTimerPoint() {
        for (int i = 0; i < textPoints.size(); i++) {
            Point point = textPoints.get(i);
            if (point.y <= -ViewUtils.measureTextSize(text, textPaint.getTextSize())) {
                point.y = getMeasuredHeight();
            } else {
                point.y -= moveDistance;
            }
        }


    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        distributePoints();

    }

    /**
     * 划分
     */
    private void distributePoints() {
        textPoints.clear();
        int measuredHeight = getMeasuredHeight();
        int measuredWidth = getMeasuredWidth();
        float textLength = ViewUtils.measureTextSize(text, textSize);
        int paddingTop = getPaddingTop();
        if (mode == WaterLampMode.SINGLE.ordinal()) {
            // 放在中间
            textPoints.add(new Point((int) ((measuredWidth) / 2 - textSize / 3), paddingTop));
        } else if (mode == WaterLampMode.DOUBLE.ordinal()) { // 两行模式
            float start = (measuredWidth - this.textSize * 2) / 2;
            for (int i = 0; i < 2; i++) {
                Point point = new Point();
                point.x = (int) (start + i * textSize + i * space);
                point.y = getPaddingTop();
                textPoints.add(point);
            }
        } else if (mode == WaterLampMode.THREE.ordinal()) {

            for (int i = 0; i < 3; i++) {
                float start = (measuredWidth - this.textSize * 2) / 3 + i * textSize;
                Point point = new Point();

                if (i == 0) {
                    point.y = paddingTop + 400;
                } else {
                    point.y = paddingTop;
                }
                if (i % 2 == 0) {

                    point.x = (int) (start + i * space);
                } else {
                    point.x = (int) (start + i * space);
                }
                textPoints.add(point);
            }
        } else {
            throw new IllegalStateException("没有这个模式");
        }

    }


    public void setTextFlash(boolean flash) {
        if (flash) {
            this.flashThread = null;
            this.flashThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    textMove();
                }
            });
            isFlash = true;
            this.flashThread.start();
        } else {
            this.thread.interrupt();
            isStart = false;
            this.thread = null;
        }


    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        if (mode == WaterLampMode.SINGLE.ordinal()) {
            Point point = textPoints.get(0);
            drawSingle(canvas, point);
        } else if (mode == WaterLampMode.DOUBLE.ordinal()) {
            for (int i = 0; i < 2; i++) {
                drawMuch(canvas, textPoints.get(i));
            }
        } else if (mode == WaterLampMode.THREE.ordinal()) {
            for (int i = 0; i < 3; i++) {
                float _currentTextSize = this.textPaint.getTextSize();
                if (i % 2 == 0) {
                    float newsTextSize = _currentTextSize - 100;
                    this.textPaint.setTextSize(newsTextSize);
                }
                drawMuch(canvas, textPoints.get(i));
                this.textPaint.setTextSize(_currentTextSize);
            }
        }

    }

    private void drawMuch(Canvas canvas, Point point) {
        drawSingle(canvas, point);
    }

    public void start() {
        this.thread = null;
        this.thread = new Thread(new Runnable() {
            @Override
            public void run() {
                textMove();
            }
        });
        isStart = true;
        this.thread.start();
    }


    public void stop() {
        this.thread.interrupt();
        isStart = false;
        this.thread = null;
    }

    private void drawSingle(Canvas canvas, Point point) {
        drawLineText(text, point.x, point.y, textPaint, canvas);
    }


    public void drawLineText(String text, int x, int y, Paint paint, Canvas canvas) {

        Matrix matrix = canvas.getMatrix();
        matrix.preRotate(90, x, y);
        canvas.save();
        canvas.concat(matrix);
        canvas.drawText(text, x, y, textPaint);
        canvas.restore();
    }


    float startY = 0;

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float endY = event.getY();
                float distance = endY - startY;
                move(distance > 0 ? moveDistance : -moveDistance);
                break;
        }
        invalidate();
        return ViewUtils.measureTextSize(text, textSize) > getMeasuredHeight();
    }


    public void move(float distance) {
        for (int i = 0; i < textPoints.size(); i++) {
            Point point = textPoints.get(i);
            if (!checkState(distance)) {
                point.y += distance;
            }
        }
    }

    public boolean checkState(float distance) {
        for (int i = 0; i < textPoints.size(); i++) {
            Point point = textPoints.get(i);
            if ((distance <= 0 && point.y < -getMeasuredWidth() / 2) || (distance >= 0 && point.y > (float) getMeasuredHeight() / 2)) {
                return true;
            }
        }
        return false;
    }


    public int getTextColor() {
        return textColor;
    }

    public void setTextColor(int textColor) {
        this.textPaint.setColor(textColor);
        invalidate();
    }

    public float getTextSize() {
        return textSize;
    }

    public void setTextSize(float textSize) {
        this.textPaint.setTextSize(textSize);
        invalidate();
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
        invalidate();
    }

    public float getSpace() {
        return space;
    }

    public void setSpace(float space) {
        this.space = space;
        invalidate();
    }

    public int getMoveDistance() {
        return moveDistance;
    }

    public void setMoveDistance(int moveDistance) {
        this.moveDistance = moveDistance;
        invalidate();
    }

    public int getMode() {
        return mode;
    }

    public void setMode(WaterLampMode mode) {
        this.mode = mode.ordinal();
        distributePoints();
        invalidate();
    }

    public boolean isFlash() {
        return isFlash;
    }

    public void setFlash(boolean flash) {
        isFlash = flash;
        if (flash && !flashThread.isAlive()) {
            flashThread.start();
        } else {
            flashThread.interrupt();
            flashThread = new Thread(this::textFlash);
            textPaint.setAlpha(255);
            invalidate();
        }
    }

    public int getFlashSpeed() {
        return flashSpeed;
    }

    public void setFlashSpeed(int flashSpeed) {
        this.flashSpeed = flashSpeed;
        invalidate();
    }

    public int getTextSpeed() {
        return textSpeed;
    }

    public void setTextSpeed(int textSpeed) {
        this.textSpeed = textSpeed;
        invalidate();
    }
}
